import {Injectable} from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {FormBase} from './form-base';
import {CustomValidators} from '@kylin/validators';
import {HttpService} from '@kylin/http';
import * as _ from 'lodash';

// todo 需要封装异步校验 例如用户名是否已经注册了这种 提前给用户提示
@Injectable({
    providedIn: 'root'
})
export class FormControlService {

    constructor(private http: HttpService) {

    }

    toFormGroup(forms: FormBase<any>[]) {
        const group: any = {};
        /**
         * 如果 controlType 类型是 title 那么这个功能是纯展示的 不应该加入动态表单构建
         */
        forms = _.compact(forms.map(i => {
            if (i.controlType === 'title') {
                return null;
            } else {
                return i;
            }
        }));

        forms.forEach(form => {
            group[form.key] = !form.required && !form.validators ? new FormControl(form.value) :
                new FormControl(form.value, {
                    updateOn: form.updateOn,
                    validators: this.handlerValidators(form, group),
                    asyncValidators: this.handlerAsyncValidators(form, group)
                });
        });
        return new FormGroup(group);
    }

    /**
     * 生成同步校验数组
     * @param form 待处理的
     * @param group 已经生成的响应式表单项目
     */
    private handlerValidators(form, group): any[] {
        const target = [];
        if (form.required) {
            target.push(Validators.required);
        }
        if (form.validators) {
            for (const i in form.validators) { // todo 基本所有校验都需要key和label,可以考虑这里统一赋值
                if (form.validators.equalToValidator) { // 当校验两个输入值相等时
                    target.push(CustomValidators.equalToValidator(form, group[form.validators.equalToValidator[0]]));
                } else {
                    target.push(CustomValidators[i](form, ...form.validators[i]));
                }
            }
        }
        return target;
    }

    /**
     * 生成异步校验数组
     */
    private handlerAsyncValidators(form, group): any[] {
        return [];
    }

    fetchSelectOptions(path: string, fetchData): Promise<any> {
        return new Promise((resolve, reject) => {
            this.http.get(path)
                .then(res => {
                    if (res.result.length === 0) {
                        resolve([]);
                    } else {
                        const options = res.result.map((i) => {
                            return {key: i[fetchData.targetKey], value: i[fetchData.targetValue]};
                        });
                        resolve(options);
                    }
                })
                .catch(err => {
                    console.log(`获取selectOptions失败`);
                    console.log(err);
                });
        });
    }
}
